Uvod u nauku o podacima - seminarski rad¶

Opis problema¶

U ovom radu, zadatak je da se na osnovu informacija o vozilima u SAD pripremi skup na nacin da se dovoljno dobro istrenira model koji ce moci da predvidi cenu vozila na osnovu ostalih parametara sem cene. U daljem tekstu ce biti prvo objasnjen skup podataka, zatim modeli koji ce se koristiti a onda i prikaz konacnih rezultata, evaluacionih metrika i testiranja istreniranog modela.

Potrebne biblioteke¶

U ovom koraku ce biti uvezene biblioteke potrebne za dalji rad

In [1]:
import numpy as np
import pandas as pd
import hvplot.pandas
import seaborn as sns
from sklearn import metrics
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error as MSE
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split

Ucitavanje podataka¶

Skup podataka nad kojim ce biti izvrsena analiza, predstavlja inforrmacije o automobilima.

Podaci su sa sledeceg linka: https://www.kaggle.com/datasets/deepcontractor/car-price-prediction-challenge?resource=download

In [2]:
data = pd.read_csv("./car_price_prediction.csv")
In [3]:
data.head()
Out[3]:
ID Price Levy Manufacturer Model Prod. year Category Leather interior Fuel type Engine volume Mileage Cylinders Gear box type Drive wheels Doors Wheel Color Airbags
0 45654403 13328 1399 LEXUS RX 450 2010 Jeep Yes Hybrid 3.5 186005 km 6.0 Automatic 4x4 04-May Left wheel Silver 12
1 44731507 16621 1018 CHEVROLET Equinox 2011 Jeep No Petrol 3 192000 km 6.0 Tiptronic 4x4 04-May Left wheel Black 8
2 45774419 8467 - HONDA FIT 2006 Hatchback No Petrol 1.3 200000 km 4.0 Variator Front 04-May Right-hand drive Black 2
3 45769185 3607 862 FORD Escape 2011 Jeep Yes Hybrid 2.5 168966 km 4.0 Automatic 4x4 04-May Left wheel White 0
4 45809263 11726 446 HONDA FIT 2014 Hatchback Yes Petrol 1.3 91901 km 4.0 Automatic Front 04-May Left wheel Silver 4
In [4]:
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 19237 entries, 0 to 19236
Data columns (total 18 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   ID                19237 non-null  int64  
 1   Price             19237 non-null  int64  
 2   Levy              19237 non-null  object 
 3   Manufacturer      19237 non-null  object 
 4   Model             19237 non-null  object 
 5   Prod. year        19237 non-null  int64  
 6   Category          19237 non-null  object 
 7   Leather interior  19237 non-null  object 
 8   Fuel type         19237 non-null  object 
 9   Engine volume     19237 non-null  object 
 10  Mileage           19237 non-null  object 
 11  Cylinders         19237 non-null  float64
 12  Gear box type     19237 non-null  object 
 13  Drive wheels      19237 non-null  object 
 14  Doors             19237 non-null  object 
 15  Wheel             19237 non-null  object 
 16  Color             19237 non-null  object 
 17  Airbags           19237 non-null  int64  
dtypes: float64(1), int64(4), object(13)
memory usage: 2.6+ MB

Objasnjenje kolona¶

In [5]:
data.shape
Out[5]:
(19237, 18)

U skupu imamo 19237 redova i 18 kolona
ID - identifikacioni broj automobila, numericka promenljiva
Price - cena automobila, numericka promenljiva
Levy - taksa za vozilo - osiguranje, string sa numerickim vrednostima
Manufacturer - marka automobila, nominalna
Model - model automobila, nominalna
Prod. year - godina proizvodnje, numericka
Category - karoserija, nominalna
Leaher interior - da li je kozni interijer, boolean - binarna
Fuel type - tip goriva, nominalna
Engine volume - zapremina motora, string sa numerickim vrednostima
Mileage - predjena kilometraza, numericka
Cylinders - broj cilindara, numericka
Gear box type - tip menjaca, nominalna
Drive wheels - tip pogona, nominalna
Doors - ova kolona treba da predstavlja broj vrata ali je format kolone los pa prikazuje datum
Wheel - strana volana, nominalna
Color - boja automobila, nominalna
Airbags - broj airbagova u automobilu, numericka

Eksploratorna analiza podataka¶

Nedostajuce vrednosti¶

In [6]:
data.isnull().sum(axis=0)
Out[6]:
ID                  0
Price               0
Levy                0
Manufacturer        0
Model               0
Prod. year          0
Category            0
Leather interior    0
Fuel type           0
Engine volume       0
Mileage             0
Cylinders           0
Gear box type       0
Drive wheels        0
Doors               0
Wheel               0
Color               0
Airbags             0
dtype: int64

Nijedna kolona nema nedostajucih vrednosti, ali je bitno proveriti da li postoji prazan string ili crtica u nekoj koloni.
Kolona koja ima crtica, primecenih pri prikazivanju prvih pet kolona je levy, pa cemo ispitati podatke u njoj.

In [7]:
sum(data.Levy == "")
Out[7]:
0
In [8]:
sum(data.Levy == "-")
Out[8]:
5819
In [9]:
sum(data.Levy == "0")
Out[9]:
0

Imamo 5819 redova sa "-", koje cemo zameniti nulom jer pretpostavka je da "-" znaci da automobil nema osiguranje.

In [10]:
data.Levy = data.Levy.replace('-',0)

Sredjivanje tipova podataka i imena kolona¶

Sledeca kolona je 'Doors' koju bi trebalo izmeniti da broj vrata ne bude datum, vec klasican broj u formatu 2-3.

In [11]:
data['Doors'] = data['Doors'].str.replace('02-Mar','2-3').replace('04-May','4-5')

Takodje imamo kolonu 'Mileage' koja sadrzi km. Vazno je izbaciti km deo i pretvoriti podatke u int

In [12]:
data['Mileage'] = data['Mileage'].str.replace('km', '')
In [13]:
data['Mileage'] = data['Mileage'].astype(int)
In [14]:
data['Levy']= data['Levy'].astype(int)
In [15]:
data["Engine volume"] = data["Engine volume"].str.replace('Turbo','')
data["Engine volume"] = data["Engine volume"].astype(float)

Zbog lakseg pristupanja kolonama kao i jasnijih imena, kolone ce biti preimenovane.

In [16]:
data = data.rename(columns={'Price':'price',
                            'Levy':'levy',
                            'Manufacturer':'manufacturer',
                            'Model':'model',
                            'Prod. year':'prod_year',
                            'Category':'category',
                            'Leather interior':'leather',
                            'Fuel type':'fuel' , 
                            'Engine volume':'engine_volume',
                            'Mileage':'mileage',
                            'Cylinders':'cylinders',
                            'Gear box type' : 'gearbox' , 
                            'Drive wheels': 'drivewheels' ,
                            'Doors': 'doors' ,
                            'Wheel':'wheel' ,
                            'Color':'color',
                            'Airbags':'airbags'})

Duplikati¶

In [17]:
data.duplicated().sum()
Out[17]:
313

Imamo 313 duplikata koje cemo izbaciti

In [18]:
data.drop_duplicates(inplace=True)

Vizuelizacija podataka¶

U ovom koraku, bice vizuelno predstavljani medjusobni odnosi razlicitih promenljivih, sa akcentom na cenu.

Kako je glavni cilj pozabaviti se cenom i dobiti predikcije za cenu automobila, prvo ce biti prikazana distribucija cene i ukoliko postoje neke ekstremne vrednosti, bice otklonjene

In [19]:
data["price"].plot.box()
plt.xticks(rotation='vertical')
Out[19]:
(array([1]), [Text(1, 0, 'price')])

Ovde vidimo da postoji nekoliko outliera, kojima cemo da se pozabavimo

In [20]:
data["price"].value_counts().sort_index()
Out[20]:
1            2
3           15
6            6
9            1
19           1
            ..
297930       2
308906       1
627220       1
872946       1
26307500     1
Name: price, Length: 2315, dtype: int64

Vidimo da je to tri vrednosti koje su dosta vece od ostalih, 627220, 872946 i 26307500, pretpostavka je da je to samo par luksuznih automobila koji mogu uticati na kasnije predikcije i otklonicemo ih iz skupa.

Takodje uocavamo da imamo neke vrednosti koje su dosta male, istrazivanjem cene polovnih vozila u USA nije za ocekivati da vozila imaju cenu ispod 500 dolara sem ako su ostecena i nisu u voznom stanju.
Posto ne postoji informacija o tome da li je vozilo osteceno ili ne, uklonicemo vrednosti ispod 500$

In [21]:
(data['price'] < 500).value_counts()
Out[21]:
False    17291
True      1633
Name: price, dtype: int64
In [22]:
data = data[data["price"] < 627220] 
data = data[data["price"] >= 500]
In [23]:
data["price"].plot.box()
plt.xticks(rotation='vertical')
Out[23]:
(array([1]), [Text(1, 0, 'price')])

Distribucija cene je sada dosta normalnija nego na prethodnoj slici.

In [24]:
sns.distplot(data['price'])
plt.legend(loc = 'best')
plt.title('Distribucija cene vozila ')
C:\Users\PC-Korisnik\anaconda3\lib\site-packages\seaborn\distributions.py:2619: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).
  warnings.warn(msg, FutureWarning)
No artists with labels found to put in legend.  Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
Out[24]:
Text(0.5, 1.0, 'Distribucija cene vozila ')

Najzastupljeniji su automobili sa cenom do 50000, sto je i realno ocekivati. Primetan je pad u broju automobila sa cenom od preko 25000 sto polako prelazi u skupocene i luksuzne automobile.

In [25]:
plt.figure(figsize = (15,7))


plt.title("Broj automobila po proizvodjacu")
plt1 = data.manufacturer.value_counts().plot(kind = 'bar')
plt1.set(xlabel = 'Proizvodjac', ylabel = 'Broj')

plt.show()

Primecujemo da oko 20 proizvodjaca predstavlja najveci broj automobila u skupu, ostali proizvodjaci imaju zanemarljiv broj u odnosu na njih. Izdvajaju se Hyundai, Toyota i Mercedes.

In [26]:
plt.figure(figsize = (15,7))
plt.title("Broj automobila po karoseriji")
plt1 = data.category.value_counts().plot(kind = 'bar')
plt1.set(xlabel = 'Karoserija', ylabel = 'Broj')

plt.show()

Najveci broj automobila je sedan ili jeep, dok pickup, kabriolet i limuzine predstavljaju veoma mali udeo. Ostale kategorije imaju priblizan broj automobila.

In [27]:
plt.figure(figsize = (15,7))

plt.title("Broj automobila po godini proizvodnje")
plt1 = data.prod_year.value_counts().plot(kind = 'bar')
plt1.set(xlabel = 'Godina', ylabel = 'Broj')

plt.show()

U skupu se nalaze automobili koji su uglavnom proizvedeni nakon 1995. godine, dok najveci broj cine oni proizvodeni izmedju 2010.i 2015. godine

In [28]:
plt.figure(figsize=(15,7))
sns.histplot(binwidth=0.5, x="category", hue="fuel", data=data, stat="count", multiple="stack")
Out[28]:
<AxesSubplot:xlabel='category', ylabel='Count'>

Jos jedna stvar koju zapazmo je da vrsta goriva zavisi od karoserije, pa je tako najvise hibrida u sedanu, hecbeku i dzipu dok skoro svi kupe automobili koriste benzin.

Posto smo gore primetili da je broj automobila starijih od 1990. godine zanemarljiv izbacicemo ih i prikazati informacije o automobilima proizvedenim nakon 1990. godine.

In [29]:
data[data["prod_year"] < 1991].shape
Out[29]:
(80, 18)

Bice izbrisano samo 86 redova, sto je zanemarljiv broj ali moze da utice na konacne predikcije.

In [30]:
data = data[data["prod_year"] > 1989]
In [31]:
plt.figure(figsize=(15,7))
sns.histplot(binwidth=0.5, x="prod_year", hue="fuel", data=data, stat="count", multiple="stack")
Out[31]:
<AxesSubplot:xlabel='prod_year', ylabel='Count'>

Ono sto je i logicno bilo pretpostaviti, godinama se menja procenat vrste goriva u automobilima, pa tako hibridi pocinju da ostvaruju uticaj tek od 2006-2007 godine. Procenat benzinaca je najveci u svim godinama dok se nakon 2015 dizel automobili skoro pa gube

In [32]:
plt.figure(figsize=(15,7))
plt.title('Godina proizvodnje i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('prod_year')['price'].mean().plot.bar()
plt.show()

Trend porasta cene sa novijim vozilima je aktuelan i kao sto je i za ocekivati najnovija vozila imaju najvise cene.
Postoji nekoliko odstupanja kao na primer 2018. godiste ima vecu cenu od 2019. ali to moze znaciti da za 2018. imamo luksuznije automobile nego u narednoj.

In [33]:
plt.figure(figsize=(15,7))
plt.title('Karoserija i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('category')['price'].mean().plot.bar()
Out[33]:
<AxesSubplot:title={'center':'Karoserija i cena'}, xlabel='category', ylabel='Cena'>

Svaka karoserija imaju drugaciju srednju vrednost, sto je i ocekaivano jer su luksuzniji automobili uglavnom u kategorijama poput kabriolet ili dzip.
Sa druge strane imamo pickup koji ima najvecu prosecnu vrednost, sto je donekle neocekivano pa mozemo da probamo da otkrijemo o cemu se radi.

In [34]:
data[data.category == 'Pickup'].shape
Out[34]:
(47, 18)
In [35]:
data[data.category == 'Pickup'].prod_year.value_counts()
Out[35]:
2012    5
2010    4
2019    4
2013    4
2008    3
2017    3
2018    3
2011    3
2005    2
2007    2
1998    2
2006    2
2004    1
2020    1
1997    1
1990    1
2016    1
2015    1
1999    1
2014    1
1996    1
2009    1
Name: prod_year, dtype: int64

Kako ovde imamo uglavnom novija vozila a videli smo da godina proizvodnje utice na cenu, mozemo zakljuciti da cenu ove kategorije odredjuje godina proizvodnje vecine pickup vozila.

In [36]:
plt.figure(figsize=(15,7))
plt.title('Broj cilindara i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('cylinders')['price'].mean().plot.bar()
Out[36]:
<AxesSubplot:title={'center':'Broj cilindara i cena'}, xlabel='cylinders', ylabel='Cena'>

Broj cilindara odredjuje cenu ali ne direktno, pa tako utice i broj vozila u skupu sa tim brojem cilindara na cenu.

In [37]:
plt.figure(figsize=(15,7))
plt.title('Vrsta goriva i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('fuel')['price'].mean().plot.bar()
plt.show()

Ovde vidimo da dizel i elektricna vozila imaju najvecu cenu, dok vozila sa CNG imaju najmanju.
Kod elektricnih vozila, godiste utice na cenu kao sto smo videli jer su to uglavnom nova vozila ali i su to takodje skupoceni modeli u svetu automobila dok dizel vozila cine vecinu u novijim automobilima u skupu.

In [38]:
plt.figure(figsize=(15,7))
plt.title('Broj vrata i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('doors')['price'].mean().plot.bar()
plt.show()
In [39]:
data[data.doors == ">5"]
Out[39]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags
171 45782173 1300 0 AUDI 50 2018 Coupe Yes Petrol 0.5 4000 1.0 Tiptronic Rear >5 Right-hand drive Blue 0
276 44810053 20385 738 CHEVROLET Cruze 2017 Sedan No Petrol 1.4 42000 4.0 Tiptronic Front >5 Left wheel Black 12
678 45800055 7213 0 BMW 525 1998 Sedan No Petrol 2.5 100000 6.0 Manual Rear >5 Left wheel Silver 6
829 45766759 30000 0 NISSAN X-Trail 2018 Pickup Yes Petrol 2.5 18794 12.0 Automatic 4x4 >5 Left wheel Black 12
870 45788787 19757 810 HYUNDAI Elantra 2016 Sedan No Petrol 1.8 113600 4.0 Tiptronic Front >5 Left wheel Grey 6
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
18795 45788558 10976 0 TOYOTA ISIS 2007 Minivan Yes Petrol 2.0 1000 4.0 Automatic Front >5 Right-hand drive White 12
18806 44839699 11917 0 FORD Escape 2007 Jeep Yes Hybrid 2.3 197000 4.0 Automatic 4x4 >5 Left wheel Black 8
19085 45794339 97219 1079 LEXUS NX 300 2018 Jeep Yes Petrol 2.0 25600 4.0 Tiptronic Front >5 Left wheel White 7
19094 45804509 11290 0 FORD Transit 2000 Goods wagon No Diesel 2.5 270000 4.0 Manual Rear >5 Left wheel Orange 1
19118 45738530 23834 0 TOYOTA Alphard 2006 Minivan No LPG 3.0 149000 6.0 Automatic 4x4 >5 Left wheel Silver 6

115 rows × 18 columns

Odnos cena izmedju automobila sa 2-3 vrata i 4-5 vrata je priblizan, ali ipak ona sa 4-5 imaju blago vecu cenu. Automobila sa vise od 5 vrata ima malo u skupu sto je prikazano i oni sadrze nekoliko automobila sa velikim cenama koje uticu na srednju vrednost.

In [40]:
plt.figure(figsize=(15,7))
plt.title('Kozni interijer i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('leather')['price'].mean().plot.bar()
plt.show()

Ovde vidimo da kozni interijer ima uticaj, oni automobili koji imaju kozni interijer imaju i vecu cenu jer se kozni interijer smatra skupocenijim.

In [41]:
plt.figure(figsize=(15,7))
plt.title('Proizvodjac i cena',fontsize = 30)
plt.ylabel("Cena")
data.groupby('manufacturer')['price'].mean().plot.bar()
plt.show()

Oni proizvodjaci koji vaze za luksuznije ili imaju sportske modele imaju vece cene, kao sto je i prikazano na slici iznad. Lambordzini ima daleko skuplje automobile od ostalih, za njim sledi Bentli, Ferari, Porse koji upravo vaze za proizvodjace koji su pomenuti.

In [42]:
plt.figure(figsize = (15,7))
sns.heatmap(data.corr(), annot = True)
plt.title("Korelacija")
plt.show()

Najveci koeficijent korelacije imaju broj cilindara i zapermina motora, dok cena najveci koeficijent ima sa godinom proizvodnje kao sto je i primeceno na grafikonima.

Priprema podataka za model¶

Feature engineering¶

Feature engineering je vazan deo procesa, kako bi se dobili sto bolji rezultati modela. To je proces selekcije, transformacije i manipulacije postojecim feature-ima za kreiranje novih i bolje resavanje problema koje ce dovesti do poboljsanih performansi modela i boljih predikcija.

Prvi feature kojim se treba pozabaviti jeste cena vozila prema kategorijama, razlikujemo one karoserije sa vecom i manjom cenom od 22000, ta cena je uzeta nakon razmatranja vizuelizacije

In [43]:
mean_price_category = data[['category', 'price']].groupby('category', as_index = False).mean()
In [44]:
normal_price = []
high_price = []

for index in range(len(mean_price_category)):
    if mean_price_category.iloc[index, 1] <= 22000:
        normal_price.append(mean_price_category.iloc[index, 0])
    else:
        high_price.append(mean_price_category.iloc[index, 0])
        
print('Kategorije sa cenom ispod 20000$: ', normal_price)
print('Kategorije sa cenom iznad 20000$: ', high_price)
Kategorije sa cenom ispod 20000$:  ['Goods wagon', 'Hatchback', 'Microbus', 'Minivan', 'Sedan']
Kategorije sa cenom iznad 20000$:  ['Cabriolet', 'Coupe', 'Jeep', 'Limousine', 'Pickup', 'Universal']
In [45]:
category_column = data['category']
category_price_data = []

for value in category_column:
    if value in normal_price:
        category_price_data.append(1)
    else:
        category_price_data.append(2)
        
data['category_price'] = category_price_data
In [46]:
data.head()
Out[46]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags category_price
0 45654403 13328 1399 LEXUS RX 450 2010 Jeep Yes Hybrid 3.5 186005 6.0 Automatic 4x4 4-5 Left wheel Silver 12 2
1 44731507 16621 1018 CHEVROLET Equinox 2011 Jeep No Petrol 3.0 192000 6.0 Tiptronic 4x4 4-5 Left wheel Black 8 2
2 45774419 8467 0 HONDA FIT 2006 Hatchback No Petrol 1.3 200000 4.0 Variator Front 4-5 Right-hand drive Black 2 1
3 45769185 3607 862 FORD Escape 2011 Jeep Yes Hybrid 2.5 168966 4.0 Automatic 4x4 4-5 Left wheel White 0 2
4 45809263 11726 446 HONDA FIT 2014 Hatchback Yes Petrol 1.3 91901 4.0 Automatic Front 4-5 Left wheel Silver 4 1

Sledeci feature je godina proizvodnje koju cemo da transformisemo u broj godina starosti tako sto ce biti oduzeta godina proizvodnje od trenutne godine.

In [47]:
year_data = data['prod_year']
age_data = []

for value in year_data:
    age_data.append(2022 - value)
    
data['age'] = age_data
len(set(age_data))
Out[47]:
31

Na kraju ce kolona tip goriva biti izmenjena, da ne bi model bio zbunjen smanjicemo vrste goriva na neke uobicajene tipove koji su zastupljeniji od ostalih.

In [48]:
data.fuel.value_counts()
Out[48]:
Petrol            9083
Diesel            3808
Hybrid            2926
LPG                868
CNG                455
Plug-in Hybrid      85
Hydrogen             1
Name: fuel, dtype: int64
In [49]:
fuel_type_data = data['fuel']
new_fuel_type_data = []

for value in fuel_type_data:
    if value in {'LPG', 'Hydrogen', 'Plug-in Hybrid', 'CNG'}:
        new_fuel_type_data.append('Other')
    else:
        new_fuel_type_data.append(value)

set(new_fuel_type_data)
Out[49]:
{'Diesel', 'Hybrid', 'Other', 'Petrol'}

Enkodiranje¶

Da bi podaci bili razumljivi modelu, potrebno je enkodirati promenljive to jest umesto vrednosti poput u koloni leather Yes ce biti 1 a No 0.
Sve kategorijske vrednosti bice zamenjene numerickim, gde ce jedan broj predstavljati jednu vrednost.
Pre toga, bitno je odabrati samo korisne kolone

In [50]:
new_data = data[["ID","price","manufacturer","model","age","category_price","leather","fuel","mileage","gearbox","drivewheels","doors","wheel","airbags"]]
In [51]:
dummy_data = pd.get_dummies(new_data, columns=["manufacturer","model","leather","fuel","drivewheels","wheel","doors", "category_price","gearbox"], drop_first=True, dtype='uint8')

Podela podataka na trening i testni skup¶

In [52]:
new_data.reset_index(drop=True)
Out[52]:
ID price manufacturer model age category_price leather fuel mileage gearbox drivewheels doors wheel airbags
0 45654403 13328 LEXUS RX 450 12 2 Yes Hybrid 186005 Automatic 4x4 4-5 Left wheel 12
1 44731507 16621 CHEVROLET Equinox 11 2 No Petrol 192000 Tiptronic 4x4 4-5 Left wheel 8
2 45774419 8467 HONDA FIT 16 1 No Petrol 200000 Variator Front 4-5 Right-hand drive 2
3 45769185 3607 FORD Escape 11 2 Yes Hybrid 168966 Automatic 4x4 4-5 Left wheel 0
4 45809263 11726 HONDA FIT 8 1 Yes Petrol 91901 Automatic Front 4-5 Left wheel 4
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
17221 45772306 5802 MERCEDES-BENZ E 350 9 1 Yes Diesel 107800 Automatic Rear 4-5 Left wheel 12
17222 45798355 8467 MERCEDES-BENZ CLK 200 23 2 Yes CNG 300000 Manual Rear 2-3 Left wheel 5
17223 45778856 15681 HYUNDAI Sonata 11 1 Yes Petrol 161600 Tiptronic Front 4-5 Left wheel 8
17224 45804997 26108 HYUNDAI Tucson 12 2 Yes Diesel 116365 Automatic Front 4-5 Left wheel 4
17225 45793526 5331 CHEVROLET Captiva 15 2 Yes Diesel 51258 Automatic Front 4-5 Left wheel 4

17226 rows × 14 columns

X predstavlja skup koji ne sadrzi cenu kako bi model mogao da uci, y prestavlja labele.

In [53]:
X=dummy_data.drop(columns='price')
y=dummy_data['price']
In [54]:
X_train , X_test , y_train , y_test = train_test_split(X,y,random_state=1,test_size=0.2)
In [55]:
X_train.head()
Out[55]:
ID age mileage airbags manufacturer_ALFA ROMEO manufacturer_ASTON MARTIN manufacturer_AUDI manufacturer_BENTLEY manufacturer_BMW manufacturer_BUICK ... fuel_Plug-in Hybrid drivewheels_Front drivewheels_Rear wheel_Right-hand drive doors_4-5 doors_>5 category_price_2 gearbox_Manual gearbox_Tiptronic gearbox_Variator
7050 45656442 9 137802 0 0 0 0 0 1 0 ... 0 0 0 0 1 0 1 0 0 0
6467 45438005 7 79000 8 0 0 0 0 0 0 ... 0 1 0 0 1 0 0 0 1 0
10683 45647914 6 448982 0 0 0 1 0 0 0 ... 0 0 0 0 1 0 1 0 0 0
4846 45809752 9 86262 4 0 0 0 0 0 0 ... 0 1 0 0 1 0 0 0 0 0
10986 45730592 13 56629 4 0 0 0 0 0 0 ... 0 1 0 0 1 0 1 0 0 0

5 rows × 1624 columns

In [56]:
X_test.head()
Out[56]:
ID age mileage airbags manufacturer_ALFA ROMEO manufacturer_ASTON MARTIN manufacturer_AUDI manufacturer_BENTLEY manufacturer_BMW manufacturer_BUICK ... fuel_Plug-in Hybrid drivewheels_Front drivewheels_Rear wheel_Right-hand drive doors_4-5 doors_>5 category_price_2 gearbox_Manual gearbox_Tiptronic gearbox_Variator
5673 45802007 11 135746 4 0 0 0 0 0 0 ... 0 1 0 0 1 0 1 0 0 0
14269 45791372 16 6000 10 0 0 0 0 0 0 ... 0 0 0 0 1 0 1 0 1 0
17826 45798064 12 100403 4 0 0 0 0 0 0 ... 0 1 0 0 1 0 0 0 0 0
2334 45776665 25 155000 2 0 0 0 0 0 0 ... 0 0 0 1 0 0 1 0 1 0
18010 45662052 12 187312 0 0 0 0 0 0 0 ... 0 1 0 0 1 0 0 0 0 0

5 rows × 1624 columns

Ovde smo podelili promenljive na skup za trening i skup za test. Ideja je da se nakon treniranja, ponasanje modela proveri nad podacima sa kojima do sada nije upoznat.

Modeli masinskog ucenja¶

Sada kada smo pripremili podatke, mozemo primeniti modele masinskog ucenja.
Modeli koje cemo primeniti su Linarna regresija i Random Forest

Linearna regresija¶

Prosta regresija je regresioni metod koji razmatra vezu izmedju jedne zavisno promenljive Y i jedne nezavisno promenljive X.

Neki od parametara:
fit_interceptbool, default=True Ovim parametrom se odredjuje da li da se racuna intercept u modelu.
n_jobsint, default=None Broj "jobova" koje ce se koristiti za izracunavanje

Random forest¶

Random forest je specijalizovan nacin klasifikacije koji funkcioniše na principu stabla odluke. Stablo odluke (engl. decision tree) je stuktura nalik binarnim stablima, gde svaki cvor predstavlja test na odredjenu karakteristiku, dok listovi stabla predstavljaju konacnu odluku stabla. Random forest se sastoji od više razlicitih stabala odluka koji nezavisno jedni od drugih klasifikuju test primer. Konacna odluka random foresta se formira kada se usrednje odlucene vrednosti svih stabala, i uzorak se svrstava u onu klasu za koju je najviše stabala glasalo.

Neki od parametara modela:
n_estimatorsint, default=100 Broj stabala u "šumi"
criterion{“squared_error”, “absolute_error”, “poisson”}, default=”squared_error”
max_depthint, default=None Maksimalna dubina stabla.

Linearna regresija¶

In [57]:
lr = LinearRegression()
lr.fit(X_train, y_train)
Out[57]:
LinearRegression()
In [58]:
reg_predict_train = lr.predict(X_train)
reg_predict_test = lr.predict(X_test)
In [59]:
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_train, reg_predict_train),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_train, reg_predict_train),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_train, reg_predict_train)),2))
Mean Absolute Error: 7474.89
Mean Squared Error: 134037937.8
Root Mean Squared Error: 11577.48
In [60]:
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_test, reg_predict_test),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_test, reg_predict_test),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_test, reg_predict_test)),2))
Mean Absolute Error: 187874.81
Mean Squared Error: 4346331103397.76
Root Mean Squared Error: 2084785.63
In [61]:
reg_predict2 = lr.predict(X_test)

Random Forest Regression¶

In [62]:
rf_reg = RandomForestRegressor(n_estimators=20, random_state=0)
rf_reg.fit(X_train, y_train)
Out[62]:
RandomForestRegressor(n_estimators=20, random_state=0)
In [63]:
rf_pred_test = rf_reg.predict(X_test)
rf_pred_train = rf_reg.predict(X_train)
In [64]:
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_train, rf_pred_train),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_train, rf_pred_train),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_train, rf_pred_train)),2))
Mean Absolute Error: 1608.07
Mean Squared Error: 12999295.59
Root Mean Squared Error: 3605.45
In [65]:
print('Mean Absolute Error:', round(metrics.mean_absolute_error(y_test, rf_pred_test),2))
print('Mean Squared Error:', round(metrics.mean_squared_error(y_test, rf_pred_test),2))
print('Root Mean Squared Error:', round(np.sqrt(metrics.mean_squared_error(y_test, rf_pred_test)),2))
Mean Absolute Error: 4497.18
Mean Squared Error: 134107488.56
Root Mean Squared Error: 11580.48

Ovde su uradjene predikcije nad test i train skupom, iz prilozenog mozemo da vidimo da bolje rezultate imaju predikcije nad train skupom ali je praksa da se predikcije rade nad testnim skupom kako bi se videlo ponasanje modela nad podacima koje do sada nije video.

U celiji ispod su prikazani rezultati predikcije cene za pojedine automobile

Da bi prikazali nekoliko rezultata kako izgledaju stvarni podaci i ono sto su modeli predvideli, moramo prvo pronaci nekoliko automobila iz y_test i predstaviti ih sa podacima koji nisu dummy i onda uporediti prave i prediktovane vrednosti

In [66]:
test_car_id = list(X_test["ID"].head(10))
In [67]:
test_car_id
Out[67]:
[45802007,
 45791372,
 45798064,
 45776665,
 45662052,
 45776995,
 45790231,
 45794822,
 45700887,
 45726679]
In [68]:
data[data['ID'] == 45802007]
Out[68]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags category_price age
5673 45802007 21395 1266 HYUNDAI Genesis 2011 Coupe Yes Petrol 3.8 135746 4.0 Automatic Front 4-5 Left wheel Grey 4 2 11
In [69]:
rf_pred_test[0]
Out[69]:
20684.8
In [70]:
reg_predict_test[0]
Out[70]:
21072.942425985355

Kako znamo pozicije u skupovima podataka na osnovu ID kolone nalazimo automobil u izvornom skupu i na osnovu toga uporedjujemo vrednosti. Random Forest je predvideo nizu cenu za 711 dolara dok je linearna regresija omasila za 320. Iz ovog jednog primera mozemo da kazemo da je Random Forest za nijansu losiji posao uradio. Da ne bismo zakljucke bazirali samo na jednom uzorku, ponovicemo pristup za jos nekoliko automobila i videti da li su slicni rezultati.

In [71]:
data[data['ID'] == 45791372]
Out[71]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags category_price age
14269 45791372 18189 0 LINCOLN Navigator 2006 Jeep Yes Petrol 5.4 6000 8.0 Tiptronic 4x4 4-5 Left wheel White 10 2 16
In [72]:
rf_pred_test[1]
Out[72]:
17467.85
In [73]:
reg_predict_test[1]
Out[73]:
34472.19573950488

Kod ovog automobila, Random Forest je dao solidno dobar rezultat dok je linearna regresija neverovatno mnogo omasila.

In [74]:
data[data['ID'] == 45798064]
Out[74]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags category_price age
17826 45798064 14069 687 HYUNDAI Elantra 2010 Sedan Yes Petrol 1.6 100403 4.0 Automatic Front 4-5 Left wheel White 4 1 12
In [75]:
rf_pred_test[2]
Out[75]:
13949.55
In [76]:
reg_predict_test[2]
Out[76]:
10245.51498335367

Ovde imamo slican slucaj, RF je omasio za samo 100 dolara dok je LR za skoro 4000

In [77]:
data[data['ID'] == 45662052]
Out[77]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags category_price age
18010 45662052 1803 574 HONDA Insight 2010 Hatchback Yes Hybrid 1.3 187312 4.0 Automatic Front 4-5 Left wheel Blue 0 1 12
In [78]:
rf_pred_test[4]
Out[78]:
1709.05
In [79]:
reg_predict_test[4]
Out[79]:
4864.438932470046

Isto i ovde

In [80]:
data[data['ID'] == 45790231]
Out[80]:
ID price levy manufacturer model prod_year category leather fuel engine_volume mileage cylinders gearbox drivewheels doors wheel color airbags category_price age
3106 45790231 21639 650 CHEVROLET Cruze 2016 Sedan Yes Petrol 1.4 99200 4.0 Tiptronic Front 4-5 Left wheel Black 10 1 6
In [81]:
rf_pred_test[6]
Out[81]:
22322.7
In [82]:
reg_predict_test[6]
Out[82]:
22920.375845366623

Ovde je za razliku od ostalih slucajeva LR dala za nijansu losiji rezultat od RF, ali iz nekoliko nasumicno odabranih primera mozemo da zakljucimo da Random Forest daje zadovoljavajuce rezultate predikcija cene za automobile dok je Linearna regresija u nekim slucajevima dosta losija.

In [ ]: